﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AlgoImpl
{
    [Serializable]
    public class ShiftRequests
    {
        private Dictionary<string, SingleRequest> m_Request = new Dictionary<string, SingleRequest>();

        public Dictionary<string, SingleRequest> Request 
        {
            get { return m_Request; }
        }

        public Dictionary<string, List<string>> GetWantedShifts()
        {
            Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
            foreach (KeyValuePair<string, SingleRequest> kvp in m_Request)
            {
                dic.Add(kvp.Key, kvp.Value.WantedShifts);
            }

            return dic;
        }

        public Dictionary<string, List<string>> GetForbidenShifts()
        {
            Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>();
            foreach (KeyValuePair<string, SingleRequest> kvp in m_Request)
            {
                dic.Add(kvp.Key, kvp.Value.ForbiddenShifts);
            }

            return dic;
        }

        public void AddWorkerWithHisRequest(string worker, List<string> wantedShifts, List<string> forbiddenShifts)
        {
            m_Request.Add(worker, new SingleRequest(wantedShifts, forbiddenShifts));
        }

        public List<string> GetWantedShiftsOfWorker(string worker)
        {
            return m_Request[worker].WantedShifts;
        }

        public bool IsShiftForbidenForWorker(string worker, string _shift)
        {
            foreach (string shift in m_Request[worker].ForbiddenShifts)
            {
                if (shift.Equals(_shift))
                {
                    return true;
                }
            }
            return false;
        }

        public bool IsShiftSetForWorker(string workerId, string Id)
        {
            foreach (string shift in m_Request[workerId].WantedShifts)
            {
                if (shift.Equals(Id))
                {
                    return true;
                }
            }
            return false;
        }

        public List<string> GetforbiddenShiftsOfWorker(string worker)
        {
            return m_Request[worker].ForbiddenShifts;
        }

        public int GetNumberOfforbiddenShiftsOfWorker(string worker)
        {
            return m_Request[worker].ForbiddenShifts.Count;
        }

        public int GetNumberOfwantedShiftsOfWorker(string worker)
        {
            return m_Request[worker].WantedShifts.Count;
        }

        public void RandomizeOrderOfShiftsOfWorkers()
        {
            Dictionary<string, SingleRequest> newRequest = new Dictionary<string, SingleRequest>();
            foreach (string worker in m_Request.Keys)
            {
                List<string> newlist = randomizeOneList(worker, m_Request[worker].WantedShifts);
                newRequest.Add(worker, new SingleRequest(newlist, m_Request[worker].ForbiddenShifts));
            }
            m_Request = newRequest;
        }

        private List<string> randomizeOneList(string worker, List<string> list)
        {
            List<int> randomList = ramdomizeListInSize(list.Count);
            List<string> newShiftRequest = new List<string>();
            
            for (int i = 0; i < list.Count; i++)
            {
                newShiftRequest.Add(list[randomList[i]]);
            }
            return newShiftRequest;
        }

        private List<int> ramdomizeListInSize(int maxRandValue)
        {
            List<int> randomList = new List<int>();
            Random randomizer = new Random();
            while (randomList.Count < maxRandValue)
            {
                int randNum = randomizer.Next(0, maxRandValue);
                if (!randomList.Contains(randNum))
                {
                    randomList.Add(randNum);
                }
            }
            return randomList;
        }
    }

    [Serializable]
    public class SingleRequest
    {

        private List<string> m_WantedShifts = new List<string>();
        private List<string> m_ForbiddenShifts = new List<string>();

        public void AddWantedShift(string shiftId)
        {
            if (!m_WantedShifts.Contains(shiftId))
            {
                m_WantedShifts.Add(shiftId);
            }
            else
            {
                throw new Exception("Shift " + shiftId + " exist");
            }
        }

        public void AddForbiddenShift(string shiftId)
        {
            if (!m_ForbiddenShifts.Contains(shiftId))
            {
                m_ForbiddenShifts.Add(shiftId);
            }
            else
            {
                throw new Exception("Shift " + shiftId + " exist");
            }
        }

        public SingleRequest(List<string> wantedShifts, List<string> forbiddenShifts)
        {
            m_WantedShifts = wantedShifts;
            m_ForbiddenShifts = forbiddenShifts;
        }

        public List<string> WantedShifts 
        {
            get { return m_WantedShifts; }
            set { m_WantedShifts = value; }
        }
        public List<string> ForbiddenShifts
        {
            get { return m_ForbiddenShifts; }
            set { m_ForbiddenShifts = value; }
        }
    }
}
